#include <windows.h>
//#include <stdio.h>
//#include <string>
//using std::string;

#include "Engine/Resource.h"
#include "Engine/Engine.h"
//#include "Engine/Utilities/File.h"

// global variables
HINSTANCE hInst;
HWND wndHandle;

// global externals
int screenWidth = 640;
int screenHeight = 480;

// forward declarations
bool initWindow(HINSTANCE hInstance);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance, 
				   LPTSTR lpCmdLine,
				   int nCmdShow)
{
	// kill program if window doesn't initialize
	if (!initWindow(hInstance)) return false;

	// initialize engine, kill if failed
	Engine engine;
	if (!engine.Initialize(&wndHandle, &hInstance)) return false;

	// variables for game update loop
	LARGE_INTEGER timeStart;
	LARGE_INTEGER timeEnd;
	LARGE_INTEGER timerFreq;
	QueryPerformanceFrequency(&timerFreq);	// CPU frequency, ticks/sec

	float fps = 0.0f;						// fps 
	float deltaTime = 0.0f;					// change in time in milliseconds

	// Windows message loop
	MSG msg;
	ZeroMemory(&msg, sizeof(msg));

	while (msg.message != WM_QUIT)
	{
		QueryPerformanceCounter(&timeStart);	// CPU time at start of loop
		
		if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		// possible FPS cap, doesn't work yet
		//if (engine.GetFPS() <= 70.0)
		//{
			// engine update and rendering
			if (!engine.Update(deltaTime)) return false;
			if (!engine.Render()) return false;
		//}
		
		QueryPerformanceCounter(&timeEnd);		// CPU time at end of loop
		
		// change in time in milliseconds between game loop updates
		deltaTime = (((timeEnd.QuadPart - timeStart.QuadPart) * 1000.0f) / timerFreq.QuadPart);

	}

	// player has quit, shutdown engine
	if (!engine.ShutDown()) return false;

	return (int) msg.wParam;
}

bool initWindow(HINSTANCE hInstance)	// create the game window
{
	// initialize the window class
	WNDCLASSEX wcex;

	wcex.cbSize			= sizeof(WNDCLASSEX);
	wcex.style			= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC)WndProc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_BIG));
	wcex.hIconSm		= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_SMALL));
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;
	wcex.lpszClassName	= "YouAreCat";
	
	RegisterClassEx(&wcex);

	// create the window
	wndHandle = CreateWindow("YouAreCat",
		"You Are Cat: The Game",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, 
		CW_USEDEFAULT,
		screenWidth, 
		screenHeight, 
		NULL, 
		NULL, 
		hInstance, 
		NULL);

	// kill the program if window not created
	if (!wndHandle) return false;

	ShowWindow(wndHandle, SW_SHOW);
	UpdateWindow(wndHandle);

	return true;
}

LRESULT CALLBACK WndProc(HWND hWnd, 
						 UINT message, 
						 WPARAM wParam, 
						 LPARAM lParam)
{
	// Callback function for any Windows-specific input (message) from user
	switch (message)
	{
		case WM_DESTROY:
			PostQuitMessage(0);
			break;
	}

	return DefWindowProc(hWnd, message, wParam, lParam);
}